Author(s): Zongcheng Li
Reviewer(s): Ying Ge, Junyi Shen
Date: 2025-12-18

1 Academic Citation

If you use this code in your work or research, we kindly request that you cite our publication:

Xiaofan Lu, et al. (2025). FigureYa: A Standardized Visualization Framework for Enhancing Biomedical Data Interpretation and Research Efficiency. iMetaMed. https://doi.org/10.1002/imm3.70005

2 需求描述 Requirement description

这篇文章自带的R代码里没找到这张图的代码……

我其实就想要基因表达和药物连线,他右侧target 和pathway的连线。

感觉用的地方其实挺多的,想学学连线的方法。

I couldn’t find the code for this graph in the R code provided with this article…

Actually, I just want the connection between gene expression and drugs, the connection on the right side of the target and pathway.

It seems that there are actually quite a few places where it can be used. I want to learn the method of connecting lines.

From https://doi.org/10.1038/s42255-019-0045-8

Fig. 5 | Effects of multidimensional hypoxia-associated signatures on drug response. a, Interaction of hypoxia-associated mRNAs, DNA methylation, miRNAs and drug response. Upregulated genes (red bars in upper panel) in hypoxia score-high ESCA negatively correlate (green lines, drug-sensitive) with the response to 17 drugs. Downregulated miRNAs (blue bars, left panel), hypomethylation (blue bars, bottom panel) for the corresponding upregulated genes positively correlate (magenta lines, drug-resistant) to drug response. The target genes and targeted pathways of drugs are listed in the panel to the right. The gold line indicates miRNA-targeted mRNAs; the red line links the drug to its target and targeted pathway. DNA-PK, DNA-dependent protein kinase; Hsp90, heat shock protein 90; KIF11, kinesin family member 11; PRKC, serine/threonine-protein kinase; SHP-1/2, Src homology 2 domain- containing protein tyrosine phosphatase 1/2; STLC, S-trityl-l-cysteine.

3 应用场景 Application Scenarios

任意两组、多组连线。

多列或上下左右的排布方式。

根据自己数据的生物学意义,来排列各个节点的顺序。或许能够出现特殊的模式,从而展示出有意义的生物学规律。

Connect any two or more groups.

Multi-column or up-down, left-right arrangement.

Arrange the order of each node based on the biological significance of your own data. Perhaps special patterns can emerge, thereby revealing meaningful biological laws.

4 环境设置 Environment Setup

source("install_dependencies.R")
## 开始安装R包...
## Starting R package installation...
## ===========================================
## 包已安装: ggplot2 
## Package already installed: ggplot2 
## 包已安装: aplot 
## Package already installed: aplot 
## 包已安装: dplyr 
## Package already installed: dplyr 
## 包已安装: scales 
## Package already installed: scales 
## 
## ===========================================
## 验证安装结果:
## Verifying installation results:
## ✓ ggplot2 已成功安装
## ✓ ggplot2 installed successfully
## ✓ aplot 已成功安装
## ✓ aplot installed successfully
## ✓ dplyr 已成功安装
## ✓ dplyr installed successfully
## ✓ scales 已成功安装
## ✓ scales installed successfully
source("crosslink.R") # From R package crosslink, https://github.com/zzwch/crosslink
source("layout.R") # From R package crosslink, https://github.com/zzwch/crosslink
source("transfromation.R") # From R package crosslink, https://github.com/zzwch/crosslink
source("utils.R") # From R package crosslink, https://github.com/zzwch/crosslink
source("crossplot.R") # From R package crosslink, https://github.com/zzwch/crosslink

library(ggplot2) # 画图 plot graph
library(aplot) # 拼图 plot composition
## aplot v0.2.9 For help: https://github.com/YuLab-SMU/aplot/issues
## 
## If you use aplot in published research, please cite the paper:
## 
## Shuangbin Xu, Qianwen Wang, Shaodi Wen, Junrui Li, Nan He, Ming Li,
## Thomas Hackl, Rui Wang, Dongqiang Zeng, Shixiang Wang, Shensuo Li,
## Chunhui Gao, Lang Zhou, Shaoguo Tao, Zijing Xie, Lin Deng, and
## Guangchuang Yu. aplot: Simplifying the creation of complex graphs to
## visualize associations across diverse data types. The Innovation. 2025,
## 6(9):100958. doi: 10.1016/j.xinn.2025.100958
## 
## Export the citation to BibTex by citation('aplot')
## 
## This message can be suppressed by:
## suppressPackageStartupMessages(library(aplot))
library(dplyr) # 数据处理 data processing
## 
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
## 
##     filter, lag
## The following objects are masked from 'package:base':
## 
##     intersect, setdiff, setequal, union
library(scales)

Sys.setenv(LANGUAGE = "en") #显示英文报错信息
options(stringsAsFactors = FALSE) #禁止chr转成factor

5 输入文件 Input File

easy_input_nodes.txt,所有节点id及其类别type。 easy_input_nodes.txt, all node ids and their category types.

easy_input_edges.txt,每两个被连起来的节点为一行。 easy_input_edges.txt, every two concatenated nodes form one line.

# 载入连线所需的节点类型
# Load the node types required for the connection
nodes <- read.table("easy_input_nodes.txt", header = T)
head(nodes)
##      id type
## 1 Gene1 Gene
## 2 Gene2 Gene
## 3 Gene3 Gene
## 4 Gene4 Gene
## 5 Gene5 Gene
## 6 Gene6 Gene
table(nodes$type)
## 
## Drug Gene Meth  Mir Path  Tar 
##    8   10   10    6    6    8
# 载入连线所需的节点间的关系
# Load the relationships between the nodes required for the connection
edges <- read.table("easy_input_edges.txt", header = T)
head(edges)
##   source target
## 1  Gene6   Mir3
## 2  Gene2   Mir1
## 3  Gene3   Mir5
## 4  Gene1   Mir4
## 5  Gene6   Mir6
## 6  Gene9   Mir6

为了画上下左三面的bar plot,需提供节点对应的数值: In order to draw the bar plots on the top, bottom and left sides, the corresponding values of the nodes need to be provided:

  • easy_input_geneData.txt
  • easy_input_methData.txt
  • easy_input_mirData.txt
# 载入画bar plot所需的数值
# Load the values required for drawing the bar plot
geneData <- read.table("easy_input_geneData.txt", header = T)
head(geneData)
##    gene        lfc
## 1 Gene1 2.03845613
## 2 Gene2 0.43505296
## 3 Gene3 0.02458533
## 4 Gene4 4.34067861
## 5 Gene5 1.79503682
## 6 Gene6 4.20195310
methData <- read.table("easy_input_methData.txt", header = T)
head(methData)
##    meth        lfc
## 1 Meth1 -0.4845682
## 2 Meth2 -0.2629383
## 3 Meth3 -0.3447941
## 4 Meth4 -0.2046605
## 5 Meth5 -0.2672850
## 6 Meth6 -0.4343072
mirData <- read.table("easy_input_mirData.txt", header = T)
head(mirData)
##    mir        lfc
## 1 Mir1 -0.1800233
## 2 Mir2 -3.7385375
## 3 Mir3 -0.4348398
## 4 Mir4 -3.0869569
## 5 Mir5 -0.3048245
## 6 Mir6 -1.3052404

6 左右连线(列之间) Left and right lines (between columns)

左右多列之间连线,用columnCross函数来画。 Draw the lines connecting multiple columns on the left and right using the columnCross function.

两列 Two columns

columns <- list(
  Target = nodes$id[nodes$type == "Tar"], # set the order as you like
  Pathway = nodes$id[nodes$type == "Path"]# set the order as you like
)
columns
## $Target
## [1] "Tar1" "Tar2" "Tar3" "Tar4" "Tar5" "Tar6" "Tar7" "Tar8"
## 
## $Pathway
## [1] "Path1" "Path2" "Path3" "Path4" "Path5" "Path6"
columnCross(edges, columns, height = 10, flank_mult = 0.1, segment_shrink = 0.2) +
     scale_color_manual(values = "navy") # 自定义线的颜色 # Customize the color of the line

ggsave("squareCross_2.pdf", width = 5, height = 5)

三列 Three columns

columns <- list(
  #用输入文件中的默认顺序 # Use the default order in the input file
  Drug = nodes$id[nodes$type == "Drug"],
  #也可以换成下面这行,手动按自己想要的顺序写入 
  # Can also be replaced with the following line, and you can manually write in the order you want
  #Drug = c("Drug3", "Drug2", "Drug1", "Drug4", "Drug5", "Drug8", "Drug7", "Drug6"),
  Target = nodes$id[nodes$type == "Tar"], # set the order as you like
  Pathway = nodes$id[nodes$type == "Path"]# set the order as you like
)
columns
## $Drug
## [1] "Drug1" "Drug2" "Drug3" "Drug4" "Drug5" "Drug6" "Drug7" "Drug8"
## 
## $Target
## [1] "Tar1" "Tar2" "Tar3" "Tar4" "Tar5" "Tar6" "Tar7" "Tar8"
## 
## $Pathway
## [1] "Path1" "Path2" "Path3" "Path4" "Path5" "Path6"
columnCross(edges, columns, height = 10, flank_mult = 0.1, segment_shrink = 0.2) +
  scale_color_manual(values = c("navy","red")) # 自定义线的颜色 # Customize the color of the line

ggsave("squareCross_3.pdf", width = 5, height = 5)

四列 Four columns

columns <- list(
  Gene = nodes$id[nodes$type == "Gene"],
  Drug = nodes$id[nodes$type == "Drug"],
  Target = nodes$id[nodes$type == "Tar"], # set the order as you like
  Pathway = nodes$id[nodes$type == "Path"]# set the order as you like
)
columns
## $Gene
##  [1] "Gene1"  "Gene2"  "Gene3"  "Gene4"  "Gene5"  "Gene6"  "Gene7"  "Gene8" 
##  [9] "Gene9"  "Gene10"
## 
## $Drug
## [1] "Drug1" "Drug2" "Drug3" "Drug4" "Drug5" "Drug6" "Drug7" "Drug8"
## 
## $Target
## [1] "Tar1" "Tar2" "Tar3" "Tar4" "Tar5" "Tar6" "Tar7" "Tar8"
## 
## $Pathway
## [1] "Path1" "Path2" "Path3" "Path4" "Path5" "Path6"
columnCross(edges, columns, height = 10, flank_mult = 0.1, segment_shrink = 0.2) +
  scale_color_manual(values = c("navy","red","orange")) # 自定义线的颜色 

# Customize the color of the line
ggsave("squareCross_4.pdf", width = 6, height = 5)

7 上下左右连线(行、列之间) Lines connecting up, down, left and right (between rows and columns)

上下左右连线,用squareCross函数来画 Draw the lines up, down, left and right using the squareCross function

top <- nodes$id[nodes$type == "Gene"] # set the order as you like
bottom <- nodes$id[nodes$type == "Meth"] # set the order as you like
left <- nodes$id[nodes$type == "Mir"] # set the order as you like
right <- nodes$id[nodes$type == "Drug"] # set the order as you like

squareCross(edges, top ,bottom, left, right, 
            height = 10, width = 10, flank_mult = 0.1,
            show_node_label = T) + # 显示node label # Show node label
  # 自定义线的颜色 # Customize the color of the line
  scale_color_manual(values = c("navy", "red", "yellow", "forestgreen"))

ggsave("squareCross_22.pdf", width = 5, height = 5)

8 复现原图 Reproduce the original image

# 例文顶部按基因变化倍数从高到低排序,底部跟顶部一致
#The top of the example text is sorted by the multiple of genetic changes from high to low, and the bottom is consistent with the top
top <- geneData$gene[order(geneData$lfc, decreasing = T)] # set the order as you like
bottom <- methData$meth[order(geneData$lfc, decreasing = T)] # In this case, Meth should be the same order with Gene
left <- nodes$id[nodes$type == "Mir"] # set the order as you like
right <- nodes$id[nodes$type == "Drug"] # set the order as you like

# 右侧要画的3列
# The three columns to be drawn on the right
columns <- list(
  Drug = nodes$id[nodes$type == "Drug"], # set the order as you like
  Target = nodes$id[nodes$type == "Tar"], # set the order as you like
  Pathway = nodes$id[nodes$type == "Path"]# set the order as you like
)

height <- 10
width <- 10
flank_mult <- c(top = 0.1, bottom = 0.1,left = 0.1, right = 0.1)

# 先分别画出3个bar plot
# First, draw three bar plots respectively
topAnn <- geneData %>%
  mutate(gene_f = factor(gene, top)) %>%
  ggplot(mapping = aes(
    newCoord(gene_f, width, flank_mult[['top']]),
    lfc)) +
  geom_bar(fill = "red",
           stat = "identity",
           width = 0.5) + # 间距跟bar同宽 # The spacing is the same width as the bar
  geom_text(mapping = aes(label = gene), angle = 90, hjust =-0.2, fontface ="italic") +
  labs(x = NULL, y = "log2(Fold Change)") +
  theme_classic() +
  theme(axis.text.x = element_blank(),
        axis.line.x = element_blank(),
        axis.ticks.x = element_blank())
#topAnn

# Bottom plot
botAnn <- methData %>%
  mutate(meth_f = factor(meth, bottom)) %>%
  ggplot(mapping = aes(newCoord(meth_f, width, flank_mult[['bottom']]),
                       lfc)) +
  geom_bar(fill = "blue",
           stat = "identity",
           width = 0.5) +
  #geom_text(mapping = aes(label = gene), angle = 90, hjust =-0.2, fontface ="italic") +
  labs(x = NULL, y = "Difference") +
  theme_classic() +
  theme(axis.text.x = element_blank(),
        axis.line.x = element_blank(),
        axis.ticks.x = element_blank())
#botAnn

# left plot
lftAnn <- mirData %>%
  mutate(mir_f = factor(mir, left)) %>%
  ggplot(mapping = aes(newCoord(mir_f, height, flank_mult[['left']]),
                       lfc)) +
  geom_bar(fill = "red",
           stat = "identity", 
           width = 0.5) +
  geom_text(mapping = aes(y = 0,label = mir), 
            #fontface ="italic", 
            vjust = -1, 
            hjust = 1) +
  labs(x = NULL, y = "log2(Fold Change)") +
  theme_classic() +
  theme(axis.text.y = element_blank(),
        axis.line.y = element_blank(),
        axis.ticks.y = element_blank()) +
  coord_flip()
#lftAnn

# 画连线并跟3个bar plot拼一起
# Draw the lines and combine them with the three bar plots
p <- (squareCross(edges, top ,bottom, left, right, height = 10, width = 10, flank_mult = 0.1) +
        #自定义配色,例文把miRNA和DNA甲基化都归为resistant,因此这两个方向的连线都用了紫色
        # Custom color matching: In the example text, both miRNA and DNA methylation are classified as resistant, so the connections in these two directions are all purple
        #实际应用时,根据自己数据的意义调整颜色
        #When applying it in practice, adjust the color according to the meaning of your data
        scale_color_manual(values = c("purple", "purple", "yellow", "green"))) %>%
  insert_top(topAnn, 0.4) %>%
  insert_bottom(botAnn, 0.4) %>%
  insert_left(lftAnn, 0.4) %>%
  
  # 在右侧加入多列之间的连线
  # Add connections between multiple columns on the right side
  insert_right(columnCross(edges, columns, height = 10, flank_mult = 0.1, segment_shrink = 0.2) +
     scale_color_manual(values = c("red", "red")) , 0.6)
p

ggsave(plot = p, filename = "squarecross.pdf", width = 8, height = 5)

9 后期处理 Post-processing

输出的pdf文件是矢量图,可以用矢量图编辑器打开(例如Illustrator)调整图形、文字。 The output pdf file is a vector graphic, which can be opened with a vector graphic editor (such as Illustrator) to adjust the graphics and text.

10 附:示例数据生成过程 Attached: Sample data generation process

# nodes
nodes <- data.frame(
  id = c(paste0("Gene", 1:10), paste0("Meth", 1:10),
         paste0("Mir", 1:6), paste0("Drug", 1:8),
         paste0("Tar", 1:8), paste0("Path", 1:6)),
  type = c(rep("Gene", 10), rep("Meth", 10), 
           rep("Mir", 6), rep("Drug", 8),
           rep("Tar", 8), rep("Path", 6))
  )
# 保存到文件 # Save to file
write.table(nodes, "easy_input_nodes.txt", quote = F, sep = "\t", row.names = F)

# edges
edges <- data.frame(rbind(
  # gene vs mir
  data.frame(
    source = sample(nodes$id[nodes$type == "Gene"],
                    replace = T, 30),
    target = sample(nodes$id[nodes$type == "Mir"],
                    replace = T, 30)),
  # gene vs drug
  data.frame(
    source = sample(nodes$id[nodes$type == "Gene"],
                    replace = T, 100),
    target = sample(nodes$id[nodes$type == "Drug"],
                    replace = T, 100)),
  # meth vs drug
  data.frame(
    source = sample(nodes$id[nodes$type == "Meth"],
                    replace = T, 100),
    target = sample(nodes$id[nodes$type == "Drug"],
                    replace = T, 100)),
  # mir vs drug
  data.frame(
    source = sample(nodes$id[nodes$type == "Mir"],
                    replace = T, 20),
    target = sample(nodes$id[nodes$type == "Drug"],
                    replace = T, 20)),
  
  # drug vs target
  data.frame(
    source = nodes$id[nodes$type == "Drug"],
    target = nodes$id[nodes$type == "Tar"]),
  # target vs path
  data.frame(
    source = sample(nodes$id[nodes$type == "Tar"],
                    replace = T, 15),
    target = sample(nodes$id[nodes$type == "Path"],
                    replace = T, 15))
))
write.table(edges, "easy_input_edges.txt", quote = F, sep = "\t", row.names = F)

# gene annotation
geneData <- data.frame(
  gene = nodes$id[nodes$type == "Gene"],
  lfc = runif(length(nodes$id[nodes$type == "Gene"]), 0, 6))
write.table(geneData, "easy_input_geneData.txt", quote = F, sep = "\t", row.names = F)

# meth annotation
methData <- data.frame(
  meth = nodes$id[nodes$type == "Meth"],
  lfc = runif(length(nodes$id[nodes$type == "Meth"]), -0.5, -0.2))
write.table(methData, "easy_input_methData.txt", quote = F, sep = "\t", row.names = F)

# mir annotation
mirData <- data.frame(
  mir = nodes$id[nodes$type == "Mir"],# set the order as you want
  lfc = runif(length(nodes$id[nodes$type == "Mir"]), -4,0))
write.table(mirData, "easy_input_mirData.txt", quote = F, sep = "\t", row.names = F)

11 Session Info

sessionInfo()
## R version 4.5.2 (2025-10-31)
## Platform: x86_64-pc-linux-gnu
## Running under: Ubuntu 24.04.3 LTS
## 
## Matrix products: default
## BLAS:   /usr/lib/x86_64-linux-gnu/openblas-pthread/libblas.so.3 
## LAPACK: /usr/lib/x86_64-linux-gnu/openblas-pthread/libopenblasp-r0.3.26.so;  LAPACK version 3.12.0
## 
## locale:
##  [1] LC_CTYPE=C.UTF-8       LC_NUMERIC=C           LC_TIME=C.UTF-8       
##  [4] LC_COLLATE=C.UTF-8     LC_MONETARY=C.UTF-8    LC_MESSAGES=C.UTF-8   
##  [7] LC_PAPER=C.UTF-8       LC_NAME=C              LC_ADDRESS=C          
## [10] LC_TELEPHONE=C         LC_MEASUREMENT=C.UTF-8 LC_IDENTIFICATION=C   
## 
## time zone: UTC
## tzcode source: system (glibc)
## 
## attached base packages:
## [1] stats     graphics  grDevices utils     datasets  methods   base     
## 
## other attached packages:
## [1] scales_1.4.0  dplyr_1.1.4   aplot_0.2.9   ggplot2_4.0.1
## 
## loaded via a namespace (and not attached):
##  [1] gtable_0.3.6       jsonlite_2.0.0     compiler_4.5.2     tidyselect_1.2.1  
##  [5] gridGraphics_0.5-1 ggplotify_0.1.3    jquerylib_0.1.4    ggfun_0.2.0       
##  [9] textshaping_1.0.4  systemfonts_1.3.1  yaml_2.3.12        fastmap_1.2.0     
## [13] R6_2.6.1           labeling_0.4.3     patchwork_1.3.2    generics_0.1.4    
## [17] knitr_1.50         yulab.utils_0.2.3  tibble_3.3.0       bslib_0.9.0       
## [21] pillar_1.11.1      RColorBrewer_1.1-3 rlang_1.1.6        cachem_1.1.0      
## [25] xfun_0.55          fs_1.6.6           sass_0.4.10        S7_0.2.1          
## [29] cli_3.6.5          withr_3.0.2        magrittr_2.0.4     digest_0.6.39     
## [33] grid_4.5.2         rappdirs_0.3.3     lifecycle_1.0.4    vctrs_0.6.5       
## [37] evaluate_1.0.5     glue_1.8.0         farver_2.1.2       ragg_1.5.0        
## [41] rmarkdown_2.30     tools_4.5.2        pkgconfig_2.0.3    htmltools_0.5.9